#include "AudioPlayer.h"

#pragma comment(lib,"Strmiids.lib")

#include "Exceptions.h"

#include <cassert>

using namespace Audio;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


AudioPlayer::AudioPlayer()
: _changeStep(s_defaultChangeStep)
{
	
}


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


AudioPlayer::~AudioPlayer()
{
	_pControl->Release();
    _pEvent->Release();
    _pGraph->Release();
	_pAudio->Release();
    CoUninitialize();
}


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


void AudioPlayer::Init()
{
	// Initialize the COM library.
    HRESULT hr = CoInitialize(NULL);
    if (FAILED(hr))
    {
		throw AudioPlayerInitException(hr);
    }

	// Create the filter graph manager and query for interfaces.
    hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&_pGraph);
    if (FAILED(hr))
    {
        throw AudioPlayerInitException(hr);
    }

	hr = _pGraph->QueryInterface(IID_IMediaControl, (void **)&_pControl);
	if (FAILED(hr))
    {
        throw AudioPlayerInitException(hr);
    }

    hr = _pGraph->QueryInterface(IID_IMediaEvent, (void **)&_pEvent);
	if (FAILED(hr))
    {
        throw AudioPlayerInitException(hr);
    }

	hr = _pGraph->QueryInterface(IID_IBasicAudio, (void **)&_pAudio);
	if (FAILED(hr))
	{
		throw AudioPlayerInitException(hr);
	}
}


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


void AudioPlayer::Play(const char *fileName)
{
	// Convert to wchar
	wchar_t wFileName[255];
	mbstowcs(wFileName, fileName, 255);

	 // Build the graph. IMPORTANT: Change this string to a file on your system.
    HRESULT hr = _pGraph->RenderFile(wFileName, NULL);
	if (FAILED(hr))
	{
		throw AudioPlayerPlayException(hr);
	}
    // Run the graph.
    hr = _pControl->Run();
    if (FAILED(hr))
    {
		throw AudioPlayerPlayException(hr);
    }
}


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


void AudioPlayer::SetVolume(int volumePercent)
{
	// Fix volume
	if (volumePercent > 100)
		volumePercent = 100;
	else if (volumePercent < 0)
		volumePercent = 0;

	_pAudio->put_Volume( TranslatePercentsToVolume(volumePercent) );
}


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


int AudioPlayer::GetVolume() const
{
	long result;
	_pAudio->get_Volume(&result);
	return TranslateVolumeToPercents(result);
}


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


void AudioPlayer::VolumeUp()
{
	SetVolume( GetVolume() + _changeStep );	
}


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void AudioPlayer::VolumeDown()
{
	SetVolume( GetVolume() - _changeStep );
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


long AudioPlayer::TranslatePercentsToVolume(int volumePercent) const
{
	return (volumePercent * 100) - 10000;
}


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


int AudioPlayer::TranslateVolumeToPercents(long volume) const
{
	return (volume + 10000) / 100;
}


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////